package br.com.kallango.server.protocolo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

public class DecodificaProtocolo extends ProtocolDecoderAdapter {

	@Override
	public void decode(IoSession session, IoBuffer buf, ProtocolDecoderOutput out) throws Exception {

		DecodeBean decodeBean = getDecodeBeanBuffer(session, buf);
		byte[] msgByte = decodeBean.getDecodeBuffer().toByteArray();

		if (decodeBean.getTamanhoMensagem() == -1) {

			if (msgByte.length < BeanProtocolo.QTD_CARACTERES_TAMANHO) {
				return;
			}

			String tamMsgStr = "";

			for (int i = 0; i < BeanProtocolo.QTD_CARACTERES_TAMANHO; i++) {
				tamMsgStr += (char) msgByte[i];
			}

			decodeBean.setTamanhoMensagem(Integer.parseInt(tamMsgStr));
			ByteArrayOutputStream baosMsg = new ByteArrayOutputStream();
			baosMsg.write(msgByte, BeanProtocolo.QTD_CARACTERES_TAMANHO, msgByte.length - BeanProtocolo.QTD_CARACTERES_TAMANHO);
			decodeBean.setDecodeBuffer(baosMsg);
			msgByte = decodeBean.getDecodeBuffer().toByteArray();
		}

		int qtdCharsPendente = decodeBean.getTamanhoMensagem() - decodeBean.getMsgPendente().size();
		int i = 0;

		for (i = 0; i < qtdCharsPendente && i < msgByte.length; i++) {
			decodeBean.getMsgPendente().write(new byte[] { msgByte[i] });
		}

		if (decodeBean.getMsgPendente().size() == decodeBean.getTamanhoMensagem()) {
			out.write(decodeBean.getMsgPendente().toByteArray());
			decodeBean.getMsgPendente().reset();
			decodeBean.setTamanhoMensagem(-1);
		}

		ByteArrayOutputStream baosMsg = new ByteArrayOutputStream();

		baosMsg.write(msgByte, i, msgByte.length - i);

		decodeBean.setDecodeBuffer(baosMsg);
		msgByte = decodeBean.getDecodeBuffer().toByteArray();

		if (msgByte.length > 0) {
			decode(session, buf, out);
		}

	}

	private static final String BUFFER_RECEIVE = "DECODE_BEAN_BUFF";

	private DecodeBean getDecodeBeanBuffer(IoSession session, IoBuffer buf)
			throws IOException {
		DecodeBean decodeBean = (DecodeBean) session
				.getAttribute(BUFFER_RECEIVE);

		if (decodeBean == null) {
			decodeBean = criaDecodeBean(session, buf);
		} else {
			addByteBuffer(decodeBean.getDecodeBuffer(), buf);
		}

		return decodeBean;
	}

	private DecodeBean criaDecodeBean(IoSession session, IoBuffer buf)
			throws IOException {
		DecodeBean decodeBean = new DecodeBean();
		session.setAttribute(BUFFER_RECEIVE, decodeBean);
		addByteBuffer(decodeBean.getDecodeBuffer(), buf);
		return decodeBean;
	}
	
	 private void addByteBuffer(ByteArrayOutputStream baos, IoBuffer buf) throws
 IOException {
		byte[] baosByte = new byte[buf.remaining()];
		buf.get(baosByte);
		baos.write(baosByte);
	}

}

